/*
 * $Id: Pair.java,v 1.1 2007-01-29 17:00:56 klose Exp $
 */
package de.fanuffel.generic.structures;

import de.fanuffel.generic.functions.Function;

/**
 * @author Karl Klose
 */
public class Pair<A, B> {

  private final A first;
  private final B second;

  public Pair(final A first, final B second) {
    super();
    this.first = first;
    this.second = second;
  }

  public A getFirst() {
    return first;
  }

  public B getSecond() {
    return second;
  }

  public static <A, B> Pair<A, B> make(A a, B b) {
    return new Pair<A, B>(a, b);
  }

  public static <A, B, X> Function<X, Pair<A, B>> factorize(
      final Function<X, A> f, final Function<X, B> g) {
    return new Function<X, Pair<A, B>>() {
      public Pair<A, B> eval(X x) {
        return new Pair<A, B>(f.eval(x), g.eval(x));
      }
    };
  }

  /*
   * Pair.pairFunction(f,g).eval(a).first = f.eval(a.first)
   * Pair.pairFunction(f,g).eval(a).second = g.eval(b.second)
   */
  public static <X, Y, V, W> Function<Pair<X, V>, Pair<Y, W>> function(
      final Function<X, Y> f, final Function<V, W> g) {
    return new Function<Pair<X, V>, Pair<Y, W>>() {
      public Pair<Y, W> eval(Pair<X, V> argument) {
        return new Pair<Y, W>(f.eval(argument.first), g.eval(argument.second));
      }
    };
  }
}
